extends CharacterBody2D

# Vars for moving
var input
@export var speed: float = 100.0
@export var gravity: float = 10

# Vars for jumping
var JumpCount = 0
@export var MaxJump: int = 2
@export var JumpForce: float = 400.0

# Wall Jump
@onready var Wall = $WallRay

# Vars for dashing
@export var DashSpeed = 600

# State Machine
enum PlayerStates {
	MOVE,
	SWORD,
	DEAD,
	DASHING
}
var CurrentState = PlayerStates.MOVE

# Other Vars
var PlayerDirection: int

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	PlayerDirection = $Sprite2D.scale.x
	if CurrentState != PlayerStates.DEAD:
		if PlayerData.PlayerHP <= 0:
			CurrentState = PlayerStates.DEAD
	
	match CurrentState:
		PlayerStates.MOVE:
			movement(delta)
		PlayerStates.SWORD:
			sword(delta)
		PlayerStates.DEAD:
			dead()
		PlayerStates.DASHING:
			dashing()

func movement(delta):
	input = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
	
	if input != 0:
		if input > 0:
			velocity.x += speed * delta
			velocity.x = clamp(speed, 100.0, speed)
			$Sprite2D.scale.x = 1
			Wall.scale.x = 1
			$Sword.position.x = 11
			# $Sprite2D.flip_h = false  # 不同的翻转图像的方法
			$AnimationPlayer.play("walk")
		if input < 0:
			velocity.x -= speed * delta
			velocity.x = clamp(-speed, 100.0, -speed)
			$Sprite2D.scale.x = -1
			Wall.scale.x = -1
			$Sword.position.x = -11
			$AnimationPlayer.play("walk")
	else:
		velocity.x = 0
		$AnimationPlayer.play("idle")
	
	# Code for jumping
	if is_on_floor():
		JumpCount = 0
	
	if !is_on_floor():
		if velocity.y < 0:
			$AnimationPlayer.play("jump")
		else:
			$AnimationPlayer.play("fall")
	
	if Input.is_action_pressed("jump") and is_on_floor() and JumpCount < MaxJump:
		JumpCount += 1
		velocity.y -= JumpForce
	if !is_on_floor() and Input.is_action_just_pressed("jump") and JumpCount < MaxJump:
		JumpCount += 1
		velocity.y -= JumpForce * 1.1
	if Input.is_action_just_released("jump") and !is_on_floor() and velocity.y < gravity:
		velocity.y = gravity
	gravity_force()
	
	if wall_collider() and Input.is_action_just_pressed("jump"):
		velocity = Vector2(-800 * PlayerDirection, -400)
	
	if Input.is_action_just_pressed("attack"):
		CurrentState = PlayerStates.SWORD
	
	if Input.is_action_just_pressed("dash"):
		CurrentState = PlayerStates.DASHING
	
	move_and_slide()


func gravity_force():
	if wall_collider() and velocity.y > 0:
		velocity.y += 0.3
	else:
		velocity.y += gravity

func input_movement(delta):
	input = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
	
	if input != 0:
		if input > 0:
			velocity.x += speed * delta
			velocity.x = clamp(speed, 100.0, speed)
			$Sprite2D.scale.x = 1
			$Sword.position.x = 11
		if input < 0:
			velocity.x -= speed * delta
			velocity.x = clamp(-speed, 100.0, -speed)
			$Sprite2D.scale.x = -1
			$Sword.position.x = -11
	else:
		velocity.x = 0
		
	# Code for jumping
	if Input.is_action_pressed("jump") and is_on_floor() and JumpCount < MaxJump:
		JumpCount += 1
		velocity.y -= JumpForce
	if !is_on_floor() and Input.is_action_just_pressed("jump") and JumpCount < MaxJump:
		JumpCount += 1
		velocity.y -= JumpForce * 1.1
	if Input.is_action_just_released("jump") and !is_on_floor() and velocity.y < gravity:
		velocity.y = gravity
	gravity_force()
		
	move_and_slide()


func dead():
	$AnimationPlayer.play("dead")
	velocity.x = 0
	gravity_force()
	move_and_slide()
	await $AnimationPlayer.animation_finished
	PlayerData.PlayerHP = 4
	PlayerData.Coin = 0
	if get_tree():
		get_tree().reload_current_scene()

func dashing():
	velocity.x += PlayerDirection * DashSpeed
	await get_tree().create_timer(0.1).timeout
	CurrentState = PlayerStates.MOVE
	
	move_and_slide()

func sword(delta):
	$AnimationPlayer.play("attack")
	
	input_movement(delta)

func wall_collider():
	return Wall.is_colliding()

func reset_states():
	CurrentState = PlayerStates.MOVE
